package com.fzkj.juc.locksupport;

import java.util.concurrent.locks.LockSupport;

/**
 * @DESCRIPTION
 */
public class LockSupportDemo {

    /**
     * LockSupport 采用发放凭证的方式来阻塞线程（凭证最多为1），park方法一次会消耗掉1个凭证，unpark一次发放一个凭证（最多为1）。
     * 当凭证为0的时候，线程会阻塞，直到有凭证。
     * @param args
     */

    public static void main(String[] args) {
        DoubleUnparkAndPark();
    }

    // 两次阻塞、两次唤醒
    private static void DoubleUnparkAndPark() {
        Thread a = new Thread(() -> {
            System.out.println("------ 进入a线程 ------");
            LockSupport.park(); // 阻塞 和之前的 wait方法作用类似
            LockSupport.park(); // 阻塞 和之前的 wait方法作用类似
            System.out.println("------ a线程被唤醒 ------");
        });
        a.start();
        Thread b = new Thread(() -> {
            LockSupport.unpark(a);
            LockSupport.unpark(a);
            System.out.println("------ 唤醒线程 ------");
        });
        b.start();
    }

    // 先唤醒 再 阻塞
    private static void UnparkBeforePark() {
        Thread a = new Thread(() -> {
            System.out.println("------ 进入a线程 ------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LockSupport.park(); // 阻塞 和之前的 wait方法作用类似
            System.out.println("------ a线程被唤醒 ------");
        });
        a.start();
        Thread b = new Thread(() -> {
            LockSupport.unpark(a);
            System.out.println("------ 唤醒线程 ------");
        });
        b.start();
    }

    // 常规多线程流程：阻塞 -> 唤醒
    private static void LockSupportSimple() {
        Thread a = new Thread(() -> {
            System.out.println("------ 进入a线程 ------");
            LockSupport.park(); // 阻塞 和之前的 wait方法作用类似
            System.out.println("------ a线程被唤醒 ------");
        });
        a.start();
        Thread b = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            LockSupport.unpark(a);
            System.out.println("------ 唤醒线程 ------");
        });
        b.start();
    }
}
